package com.zja.www.dao.impl;

import com.zja.www.dao.ScheduleDao;
import com.zja.www.entity.Schedule;
import com.zja.www.util.DBUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class ScheduleDaoImpl implements ScheduleDao {
    private final Connection connection;

    public ScheduleDaoImpl() {
        this.connection = DBUtil.getConnection();
        if (this.connection == null) {
            throw new RuntimeException("无法获取数据库连接");
        }

    }


    @Override
    public boolean insert(Schedule schedule) {
        String sql = "INSERT INTO schedules (doctor_id, date, start_time, end_time, max_appointments) VALUES (?,?,?,?,?)";
        try (PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            ps.setInt(1, schedule.getDoctorId());
            ps.setTimestamp(2, schedule.getDate());
            ps.setString(3, schedule.getStartTime());
            ps.setString(4, schedule.getEndTime());
            ps.setInt(5, schedule.getMaxAppointments());

            int affectedRows = ps.executeUpdate();
            if (affectedRows > 0) {
                try (ResultSet rs = ps.getGeneratedKeys()) {
                    if (rs.next()) {
                        schedule.setId(rs.getInt(1));
                    }
                }
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean update(Schedule schedule) {
        String sql = "UPDATE schedules SET doctor_id=?, date=?, start_time=?, end_time=?, " +
                "max_appointments=?, booked_appointments=? WHERE id=?";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, schedule.getDoctorId());
            ps.setTimestamp(2, schedule.getDate());
            ps.setString(3, schedule.getStartTime());
            ps.setString(4, schedule.getEndTime());
            ps.setInt(5, schedule.getMaxAppointments());
            ps.setInt(6, schedule.getBookedAppointments());
            ps.setInt(7, schedule.getId());

            return ps.executeUpdate() > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean delete(int scheduleId) {
        String sql = "DELETE FROM schedules WHERE id=?";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, scheduleId);
            return ps.executeUpdate() > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Schedule getById(int scheduleId) {
        String sql = "SELECT * FROM schedules WHERE id=?";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, scheduleId);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    return mapResultSetToSchedule(rs);
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Schedule> getByDate(Timestamp date) {
        List<Schedule> schedules = new ArrayList<>();
        String sql = "SELECT * FROM schedules WHERE DATE(date)=DATE(?)";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setTimestamp(1, date);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    schedules.add(mapResultSetToSchedule(rs));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return schedules;
    }

    @Override
    public List<Schedule> getByDoctor(int doctorId) {
        List<Schedule> schedules = new ArrayList<>();
        String sql = "SELECT * FROM schedules WHERE doctor_id=?";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, doctorId);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    schedules.add(mapResultSetToSchedule(rs));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return schedules;
    }

    @Override
    public List<Schedule> getByDepartment(int departmentId) {
        List<Schedule> schedules = new ArrayList<>();
        String sql = "SELECT s.* FROM schedules s JOIN doctor d ON s.doctor_id=d.id WHERE d.department_id=?";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, departmentId);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    schedules.add(mapResultSetToSchedule(rs));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return schedules;
    }

    @Override
    public boolean checkScheduleConflict(int doctorId, Timestamp date, String startTime, String endTime) {
        String sql = "SELECT COUNT(*) FROM schedules WHERE doctor_id=? AND date=? " +
                "AND ((start_time <= ? AND end_time >= ?) OR " +
                "(start_time >= ? AND start_time <= ?))";
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ps.setInt(1, doctorId);
            ps.setTimestamp(2, date);
            ps.setString(3, endTime);
            ps.setString(4, startTime);
            ps.setString(5, startTime);
            ps.setString(6, endTime);

            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    return rs.getInt(1) > 0;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    private Schedule mapResultSetToSchedule(ResultSet rs) throws SQLException {
        Schedule schedule = new Schedule();
        schedule.setId(rs.getInt("id"));
        schedule.setDoctorId(rs.getInt("doctor_id"));
        schedule.setDate(rs.getTimestamp("date"));
        schedule.setStartTime(rs.getString("start_time"));
        schedule.setEndTime(rs.getString("end_time"));
        schedule.setMaxAppointments(rs.getInt("max_appointments"));
        schedule.setBookedAppointments(rs.getInt("booked_appointments"));
        return schedule;
    }
}
